home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Mac OS SDK / Dev.CD Jul 99 SDK1.toast / Development Kits / Mac OS / QuickDraw3D 1.6 SDK / Mac SampleCode Previous / Geometry Samples- Mac / BoxPaint+ / sources / BoxPaint_document.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-18  |  25.8 KB  |  1,131 lines  |  [TEXT/CWIE]

  1. /******************************************************************************
  2.  **                                                                             **
  3.  **     Module:        BoxPaint_document.c                                         **
  4.  **                                                                          **
  5.  **                                                                          **
  6.  **     Purpose:     Code for a generic document                                 **
  7.  **                                                                          **
  8.  **                                                                          **
  9.  **     Authors:    Michael Bishop                                             **
  10.  **                 Nick Thompson                                             **
  11.  **                 Robert Dierkes                                             **
  12.  **                                                                          **
  13.  **     Copyright (C) 1996-1997 Apple Computer, Inc.  All rights reserved.     **
  14.  **                                                                          **
  15.  **                                                                          **
  16.  *****************************************************************************/
  17.  
  18.  
  19.  
  20. /******************************************************************************
  21.  **                                                                             **
  22.  **                                INCLUDES                                     **
  23.  **                                                                             **
  24.  *****************************************************************************/
  25.  
  26. #include    <Quickdraw.h>    /*    For Show/HideCursor routines    */
  27. #include    <assert.h>
  28.  
  29. #include    "BoxPaint_document.h"
  30. #include    "BoxPaint_documentStructure.h"
  31.  
  32. #include    "BoxPaint_Support.h"
  33. #include    "BoxPaint_window.h"
  34. #include    "BoxPaint_texture.h"
  35. #include    "BoxPaint_utility.h"
  36. #include    "BoxPaint_cursor3D.h"
  37.  
  38. #include    "PictRead.h"
  39.  
  40.  
  41. /*
  42. **    QuickDraw 3D stuff
  43. */
  44. #include    "QD3DMath.h"
  45. #include    "QD3DCamera.h"
  46. #include    "QD3DTransform.h"
  47. #include    "QD3DGroup.h"
  48. #include    "QD3DShader.h"
  49. #include    "QD3DStorage.h"
  50. #include    "QD3DIO.h"
  51. #include    "QD3DPick.h"
  52. #include    "QD3DRenderer.h"
  53. #include    "QD3DAcceleration.h"
  54.  
  55.  
  56.  
  57.  
  58. /******************************************************************************
  59.  **                                                                             **
  60.  **                                Local Functions                                 **
  61.  **                                                                             **
  62.  *****************************************************************************/
  63.  
  64. static void Document_Init(
  65.     DocumentHdl    theDocument);
  66.     
  67. static unsigned long Document_DoPick(
  68.     DocumentPtr        theDocument,
  69.     TQ3PickObject    pickObject);
  70.     
  71. static TQ3PickObject Document_NewPick(
  72.     TQ3WindowPointPickData    *pWPPData);
  73.  
  74. static TQ3Status Document_GetPickingInfo(
  75.     DocumentHdl            theDocument,
  76.     TQ3PickObject        pickObject,
  77.     TQ3Param2D            *pTo,
  78.     TQ3GeometryObject    *pLastHitObject);
  79.  
  80.  
  81. /*===========================================================================*\
  82.  *
  83.  *    Routine:    Document_New()
  84.  *
  85.  *    Comments:    Loads a new Document with a blank (white) canvas for a texture
  86.  *
  87. \*===========================================================================*/
  88.  
  89. DocumentHdl Document_New(void)
  90. {
  91.     DocumentHdl theDocument = (DocumentHdl)Utility_MemoryNew( sizeof(DocumentRec)) ;
  92.     
  93.     if( theDocument != NULL )
  94.     {
  95.         Document_Init(theDocument);
  96.         
  97.         /*
  98.         **    Get a window for it
  99.         */
  100.         (**theDocument).fWindow = Window_New();
  101.         if ((**theDocument).fWindow == NULL) goto bail;
  102.         
  103.         /*
  104.         **    store a reference to the document record in the window's refcon
  105.         */
  106.         Window_SetDocument((**theDocument).fWindow, theDocument ) ;
  107.         
  108.         /*
  109.         **    sets up the 3d data for the scene. Create view for QuickDraw 3D.
  110.         */
  111.         (**theDocument).fView = MyNewView( (**theDocument).fWindow ) ;
  112.         
  113.         if ((**theDocument).fView == NULL) {
  114.             BP_DebugString("View could not be created!");
  115.             goto bail;    }
  116.         
  117.         /*
  118.         **    the main display group:
  119.         */
  120.         (**theDocument).fModel = MyNewModel() ;
  121.         if ((**theDocument).fModel == NULL) goto bail;
  122.     
  123.         /*
  124.         **    the drawing styles:
  125.         */
  126.         (**theDocument).fInterpolation =
  127.                 Q3InterpolationStyle_New(kQ3InterpolationStyleNone) ;
  128.         if ((**theDocument).fInterpolation == NULL) goto bail;
  129.         
  130.         (**theDocument).fBackFacing =
  131.                 Q3BackfacingStyle_New(kQ3BackfacingStyleRemove ) ;
  132.         if ((**theDocument).fBackFacing == NULL) goto bail;
  133.         
  134.         (**theDocument).fFillStyle =
  135.                 Q3FillStyle_New(kQ3FillStyleFilled ) ;
  136.         if ((**theDocument).fFillStyle == NULL) goto bail;
  137.  
  138.         (**theDocument).fCursor3D = Cursor3D_New(NULL);
  139.         if ((**theDocument).fCursor3D == NULL) goto bail;
  140.         
  141.         Cursor3D_Hide((**theDocument).fCursor3D);
  142.         
  143.         /*
  144.         **    By passing NULL as the first parameter, we tell    the function to
  145.         **    make a blank offscreen
  146.         */
  147.         (**theDocument).fTexture = Texture_New();
  148.         if ((**theDocument).fTexture == NULL) goto bail;
  149.  
  150.         /*
  151.         **    Add it to the model
  152.         */
  153.         Texture_SetToGroup((**theDocument).fTexture, (**theDocument).fModel) ;
  154.  
  155.     }
  156.     return theDocument ;
  157. bail:
  158.     Document_Dispose(theDocument);
  159.     theDocument = NULL;
  160.     return theDocument;
  161. }
  162.  
  163.  
  164. /*===========================================================================*\
  165.  *
  166.  *    Routine:    Document_Dispose()
  167.  *
  168.  *    Comments:    Deallocates and deletes all the data in a document
  169.  *
  170. \*===========================================================================*/
  171.  
  172. void Document_Dispose( DocumentHdl theDocument)
  173. {
  174.     assert(theDocument != NULL);
  175.     assert(*theDocument != NULL);
  176.     
  177.     if ((**theDocument).fReferenceCount    > 1)    {
  178.         (**theDocument).fReferenceCount--;
  179.     }
  180.     
  181.     else    {
  182.         
  183.         if ((**theDocument).fView != NULL)
  184.             Q3Object_Dispose((**theDocument).fView) ;
  185.             
  186.         if ((**theDocument).fModel != NULL)
  187.             Q3Object_Dispose((**theDocument).fModel) ;
  188.             
  189.         if ((**theDocument).fInterpolation != NULL)
  190.             Q3Object_Dispose((**theDocument).fInterpolation) ;
  191.             
  192.         if ((**theDocument).fBackFacing != NULL)
  193.             Q3Object_Dispose((**theDocument).fBackFacing) ;
  194.             
  195.         if ((**theDocument).fFillStyle != NULL)
  196.             Q3Object_Dispose((**theDocument).fFillStyle) ;
  197.         
  198.         if ((**theDocument).fTexture != NULL)
  199.             Texture_Dispose((**theDocument).fTexture);
  200.         
  201.         if ((**theDocument).fCursor3D != NULL)
  202.             Cursor3D_Dispose((**theDocument).fCursor3D);
  203.         
  204.         if ((**theDocument).fWindow != NULL)
  205.             Window_Dispose ( (**theDocument).fWindow ) ;
  206.  
  207.         /*
  208.         **    Do this last
  209.         */
  210.         DisposeHandle( (Handle)theDocument ) ;
  211.     
  212.     }
  213. }
  214.  
  215.  
  216. /*===========================================================================*\
  217.  *
  218.  *    Routine:    Document_GetReference()
  219.  *
  220.  *    Comments:    Returns a reference to a document object
  221.  *
  222. \*===========================================================================*/
  223.  
  224. DocumentHdl    Document_GetReference(DocumentHdl theDocument)
  225. {
  226.     assert(theDocument != NULL);
  227.     assert(*theDocument != NULL);
  228.     
  229.     (**theDocument).fReferenceCount++;
  230.     
  231.     return theDocument;
  232. }
  233.  
  234.  
  235. /*===========================================================================*\
  236.  *
  237.  *    Routine:    Document_GetTexture()
  238.  *
  239.  *    Comments:    Returns the Texture object associated with a document
  240.  *
  241. \*===========================================================================*/
  242.  
  243. TextureHdl    Document_GetTexture(DocumentHdl theDocument)
  244. {
  245.     assert(theDocument != NULL);
  246.     assert(*theDocument != NULL);
  247.     
  248.     return (**theDocument).fTexture;
  249. }
  250.  
  251.  
  252. /*===========================================================================*\
  253.  *
  254.  *    Routine:    Document_GetCamera()
  255.  *
  256.  *    Comments:    Returns the Camera associated with the document
  257.  *
  258. \*===========================================================================*/
  259.  
  260. TQ3CameraObject        Document_GetCamera(DocumentHdl    theDocument)
  261. {
  262.     TQ3CameraObject    theCamera;
  263.     
  264.     assert(theDocument != NULL);
  265.     assert(*theDocument != NULL);
  266.     
  267.     Q3View_GetCamera((**theDocument).fView, &theCamera);
  268.     
  269.     return theCamera;
  270. }
  271.  
  272.  
  273. /*===========================================================================*\
  274.  *
  275.  *    Routine:    Document_GetRendererPreferences()
  276.  *
  277.  *    Comments:    Returns the Renderer Preferences associated with the document
  278.  *
  279. \*===========================================================================*/
  280.  
  281. TQ3Status    Document_GetRendererPreferences(DocumentHdl    theDocument,
  282.                                             long        *theVendorID,
  283.                                             long        *theEngineID)
  284. {
  285.     TQ3RendererObject    theRenderer;
  286.     TQ3Status            theStatus = kQ3Success;
  287.     
  288.     assert(theDocument != NULL);
  289.     assert(*theDocument != NULL);
  290.     
  291.     if (Q3View_GetRenderer((**theDocument).fView, &theRenderer) != kQ3Failure)
  292.     {
  293.         if (Q3Renderer_GetType(theRenderer) == kQ3RendererTypeInteractive)
  294.             Q3InteractiveRenderer_GetPreferences(theRenderer, theVendorID, theEngineID);
  295.         else theStatus = kQ3Failure;
  296.         
  297.         Q3Object_Dispose(theRenderer);
  298.         
  299.     } else theStatus = kQ3Failure;
  300.     
  301.     return theStatus;
  302. }
  303.  
  304. /*===========================================================================*\
  305.  *
  306.  *    Routine:    Document_SetRendererPreferences()
  307.  *
  308.  *    Comments:    Sets the Renderer Preferences
  309.  *
  310. \*===========================================================================*/
  311.  
  312. TQ3Status    Document_SetRendererPreferences(DocumentHdl    theDocument,
  313.                                             long        theVendorID,
  314.                                             long        theEngineID)
  315. {
  316.     TQ3RendererObject    theRenderer;
  317.     TQ3Status            theStatus = kQ3Success;
  318.     
  319.     assert(theDocument != NULL);
  320.     assert(*theDocument != NULL);
  321.     
  322.     if (Q3View_GetRenderer((**theDocument).fView, &theRenderer) != kQ3Failure)
  323.     {
  324.         if (Q3Renderer_GetType(theRenderer) == kQ3RendererTypeInteractive)
  325.         {
  326.             Q3InteractiveRenderer_SetPreferences(theRenderer, theVendorID, theEngineID);
  327.             Q3View_SetRenderer((**theDocument).fView, theRenderer);
  328.         }
  329.         else theStatus = kQ3Failure;
  330.         
  331.         Q3Object_Dispose(theRenderer);
  332.         
  333.     } else theStatus = kQ3Failure;
  334.     
  335.     
  336.     return theStatus;
  337. }
  338.  
  339. /*===========================================================================*\
  340.  *
  341.  *    Routine:    Document_Open()
  342.  *
  343.  *    Comments:    Loads a new Document with a Pict for a texture
  344.  *
  345. \*===========================================================================*/
  346.  
  347. TQ3Status Document_Open(DocumentHdl theDocument)
  348. {
  349.     PicHandle    thePict = NULL;
  350.     
  351.     assert(theDocument != NULL);
  352.     assert(*theDocument != NULL);
  353.     
  354.     thePict =  GetPICTFile();
  355.     
  356.     if (thePict == NULL)
  357.         return    kQ3Failure;
  358.     
  359.     if ( theDocument != NULL )
  360.     {
  361.         /*
  362.         **    Set the Picture in the Texture
  363.         */
  364.         if (Texture_SetPict((**theDocument).fTexture, thePict) == kQ3Failure)
  365.             goto bail;
  366.  
  367.         /*
  368.         **    Add that texture to the group
  369.         */
  370.         if (Texture_SetToGroup( (**theDocument).fTexture,
  371.                                 (**theDocument).fModel ) == kQ3Failure)
  372.             goto bail;
  373.     }    
  374.  
  375.     return kQ3Success;
  376.     
  377. bail:
  378.     KillPicture(thePict);
  379.     return kQ3Failure;    
  380.     
  381. }
  382.  
  383.  
  384. /*===========================================================================*\
  385.  *
  386.  *    Routine:    Document_Save()
  387.  *
  388.  *    Comments:    If you can figure out how to save the model,
  389.  *                This is a good place to put in that code :)
  390.  *
  391. \*===========================================================================*/
  392.  
  393. TQ3Status Document_Save(DocumentHdl    theDocument)
  394. {
  395.     assert(theDocument != NULL);
  396.     assert(*theDocument != NULL);
  397.     
  398.     /*
  399.     **    in the meantime, no op
  400.     */
  401.     theDocument;
  402.     return kQ3Failure;
  403. }
  404.  
  405.  
  406. /*===========================================================================*\
  407.  *
  408.  *    Routine:    Document_Draw()
  409.  *
  410.  *    Comments:    Draws the document in the current DrawContext
  411.  *
  412. \*===========================================================================*/
  413.  
  414. TQ3Status Document_Draw( DocumentPtr theDocument )
  415. {    
  416.     TQ3Status        status = kQ3Failure;
  417.     
  418.     assert(theDocument != NULL);
  419.     
  420.     if ((status = Q3View_StartRendering(theDocument->fView)) != kQ3Failure)
  421.     do {
  422.         Document_SubmitScene( theDocument ) ;
  423.     } while (Q3View_EndRendering(theDocument->fView) == kQ3ViewStatusRetraverse );
  424.     
  425. bail:
  426.     
  427.     return status ;
  428.  
  429. }
  430.  
  431.  
  432. /*===========================================================================*\
  433.  *
  434.  *    Routine:    Document_Remap()
  435.  *
  436.  *    Comments:    Creates a higher resolution offscreen pixmap to texture our
  437.  *                box with. Uses the original picture and draws it into a new
  438.  *                buffer.
  439.  *
  440. \*===========================================================================*/
  441.  
  442. TQ3Status Document_Remap(DocumentHdl theDocument, long newResolution)
  443. {
  444.     assert(theDocument != NULL);
  445.     assert(*theDocument != NULL);
  446.     
  447.     if (Texture_GetResolution((**theDocument).fTexture) == newResolution)
  448.     return kQ3Success;
  449.     
  450.     Texture_SetResolution((**theDocument).fTexture,  newResolution);
  451.  
  452.     Texture_SetToGroup( (**theDocument).fTexture, (**theDocument).fModel );
  453.     
  454.     HLock((Handle)theDocument);
  455.     Document_Draw(*theDocument);
  456.     HUnlock((Handle)theDocument);
  457.     
  458.     return kQ3Success;
  459. }
  460.  
  461.  
  462. /*===========================================================================*\
  463.  *
  464.  *    Routine:    Document_SubmitScene()
  465.  *
  466.  *    Comments:    If you make a function like this, you can easily use it
  467.  *    inside a Rendering or Picking or BoundingSphere/Box loop
  468.  *    (See Document_Draw)
  469.  *
  470. \*===========================================================================*/
  471.  
  472. TQ3Status Document_SubmitScene( DocumentPtr theDocument ) 
  473. {        
  474.     TQ3Status    theStatus = kQ3Success;
  475.     
  476.     assert(theDocument != NULL);
  477.     
  478.     /*
  479.     **    Interpolation
  480.     */
  481.     if (Q3Style_Submit(    theDocument->fInterpolation,
  482.                         theDocument->fView) == kQ3Failure)
  483.         theStatus = kQ3Failure;
  484.         
  485.     /*
  486.     **    BackFacing
  487.     */
  488.     if (Q3Style_Submit(    theDocument->fBackFacing ,
  489.                         theDocument->fView) == kQ3Failure)
  490.         theStatus = kQ3Failure;
  491.         
  492.     /*
  493.     **    FillStyle
  494.     */
  495.     if (Q3Style_Submit(    theDocument->fFillStyle,
  496.                         theDocument->fView) == kQ3Failure)
  497.         theStatus = kQ3Failure;
  498.         
  499.     /*
  500.     **    Push
  501.     */
  502.     if (Q3Push_Submit(theDocument->fView) == kQ3Failure)
  503.         theStatus = kQ3Failure;
  504.         
  505.     /*
  506.     **    Rotation
  507.     */
  508.     if (Q3MatrixTransform_Submit(    &theDocument->fRotation,
  509.                                     theDocument->fView) == kQ3Failure)
  510.         theStatus = kQ3Failure;
  511.  
  512.     /*
  513.     **    Model
  514.     */
  515.     if (Q3DisplayGroup_Submit(    theDocument->fModel,
  516.                                 theDocument->fView) == kQ3Failure)
  517.         theStatus = kQ3Failure;
  518.         
  519.     /*
  520.     **    Pop
  521.     */
  522.     if (Q3Pop_Submit(theDocument->fView) == kQ3Failure)
  523.         theStatus = kQ3Failure;
  524.  
  525.  
  526.     HLock((Handle)theDocument->fCursor3D);
  527.     
  528.     /*
  529.     **    Cursor
  530.     */
  531.     if (Cursor3D_Submit(*(theDocument->fCursor3D),
  532.                         theDocument->fView) == kQ3Failure)
  533.         theStatus = kQ3Failure;
  534.         
  535.     HUnlock((Handle)theDocument->fCursor3D);
  536.  
  537.  
  538.     return kQ3Success ;
  539. }
  540.  
  541.  
  542. /*===========================================================================*\
  543.  *
  544.  *    Routine:    Document_Rotate()
  545.  *
  546.  *    Comments:    Rotates the model around while the mouse button is down.
  547.  *
  548. \*===========================================================================*/
  549.  
  550. void    Document_Rotate(DocumentHdl    theDocumentHdl)
  551. {
  552.     TQ3Point2D     newMouse;
  553.     TQ3Point2D    oldPoint;
  554.     long         mouseChanged = 0;
  555.     float        dx, dy;
  556.     float        width, height;
  557.     float        xRot, yRot;
  558.     DocumentPtr    theDocument;
  559.     
  560.     assert(theDocumentHdl != NULL);
  561.     
  562.     HideCursor();
  563.     
  564.     HLock((Handle)theDocumentHdl);
  565.  
  566.     theDocument = *theDocumentHdl;
  567.     
  568.     /*
  569.     **    get the mouse in local co-ordinates,
  570.     **    local to the  current GrafPort
  571.     */
  572.     Utility_MyGetMouse(&oldPoint);
  573.     
  574.     width = theDocument->fWindow->portRect.left - theDocument->fWindow->portRect.right;
  575.     height = theDocument->fWindow->portRect.bottom - theDocument->fWindow->portRect.top;
  576.  
  577.     while (Utility_MyStillDown()) {
  578.     
  579.         Utility_MyGetMouse(&newMouse);
  580.  
  581.         dx = oldPoint.y - newMouse.y;
  582.         dy = newMouse.x - oldPoint.x;
  583.         
  584.         if ((dx != 0) || (dy != 0)) {
  585.             TQ3Matrix4x4        tempMatrix;
  586.             
  587.             xRot = ((float) dx * kQ3Pi) / width;
  588.             yRot = ((float) dy * kQ3Pi) / height;
  589.  
  590.             if ((xRot != 0.0) || (yRot != 0.0)) {
  591.                 Q3Matrix4x4_SetRotate_XYZ(&tempMatrix, xRot, yRot, 0.0);
  592.                 Q3Matrix4x4_Multiply(&theDocument->fRotation, &tempMatrix, &theDocument->fRotation);
  593.  
  594.                 mouseChanged = 1;
  595.                 Document_Draw(theDocument);
  596.             }
  597.         }
  598.         oldPoint.x = newMouse.x; oldPoint.y = newMouse.y;
  599.     }
  600.  
  601.     ShowCursor();
  602.     
  603.     HUnlock((Handle)theDocumentHdl);
  604.     
  605. }
  606.  
  607.  
  608. /*===========================================================================*\
  609.  *
  610.  *    Routine:    Document_DrawOnTexture()
  611.  *
  612.  *    Comments:    As the cursor moves this paints on the texture with the
  613.  *                selected brush and color.
  614.  *
  615. \*===========================================================================*/
  616.  
  617. TQ3Status Document_DrawOnTexture( DocumentHdl pDocument)
  618. {
  619.  
  620.     TQ3Point2D                newPoint,
  621.                             oldPoint;
  622.     TQ3WindowPointPickData    wppData;
  623.     TQ3PickObject            pickObject;
  624.     TQ3Param2D                from,
  625.                             to;
  626.     TQ3Status                mainStatus    = kQ3Failure,
  627.                             status        = kQ3Success;
  628.     Boolean                    firstTime;
  629.     TQ3GeometryObject        theLastHitObject = NULL;
  630.     
  631.     
  632.     assert(pDocument != NULL);
  633.     
  634.     
  635.     from.u = -1.0;
  636.     from.v = -1.0;
  637.     
  638.     HLock((Handle)pDocument);
  639.     HLock((Handle)(**pDocument).fTexture);
  640.     
  641.     /*
  642.     **    Swap the quickdraw Cursor for ours
  643.     */
  644.     HideCursor();
  645.     Cursor3D_Show((**pDocument).fCursor3D);
  646.  
  647.     if (((**pDocument).fTexture == NULL) || (*(**pDocument).fTexture == NULL))
  648.     {
  649.         BP_DebugString("((**pDocument).fTexture == NULL) || (*(**pDocument).fTexture == NULL)");
  650.         goto bail;
  651.     }
  652.     
  653.     /*
  654.     **    Create a pick
  655.     */
  656.     if((pickObject = Document_NewPick(&wppData)) == NULL) {
  657.          BP_DebugString("Document_DrawOnTexture: pickObject == NULL.");
  658.         goto bail;
  659.     }
  660.  
  661.     /*
  662.     **    Track the mouse and draw where it intersects the geometry
  663.     */
  664.     firstTime = true;
  665.     oldPoint.x = oldPoint.y = 0;
  666.     while (Utility_MyStillDown()) {
  667.  
  668.         Utility_MyGetMouse(&newPoint);
  669.  
  670.         /*
  671.         **    Did mouse move?
  672.         */
  673.         if (oldPoint.x == newPoint.x  &&
  674.             oldPoint.y == newPoint.y) {
  675.             continue;
  676.         }
  677.  
  678.         /*
  679.         **    Save new mouse position
  680.         */
  681.         oldPoint = newPoint;
  682.  
  683.         /*
  684.         **    Adjust the pick point
  685.         */
  686.         wppData.point = newPoint;
  687.  
  688.         if (Q3WindowPointPick_SetPoint(pickObject, &wppData.point) == kQ3Failure) {
  689.             goto bail;
  690.         }
  691.  
  692.         if (Document_DoPick(*pDocument, pickObject) == 0) {
  693.             /*
  694.             **    No geometries hit
  695.             */
  696.             continue;
  697.         }
  698.             
  699.         status = Document_GetPickingInfo(pDocument, pickObject, &to, &theLastHitObject);
  700.  
  701.         if ((status == kQ3Success)  && ((from.u != to.u) || (from.v != to.v)))
  702.         {
  703.             TexturePtr    theTexture    = NULL;
  704.  
  705.             if (firstTime)
  706.             {
  707.                 /*
  708.                 **    Texture_PaintLineRC needs valid row & column
  709.                 */
  710.                 from = to;
  711.                 firstTime = false;
  712.             }
  713.             
  714.             /*
  715.             **    Paint the line
  716.             */
  717.             theTexture = *((**pDocument).fTexture);
  718.  
  719.             Texture_PaintLineUV(theTexture, from, to);
  720.                 
  721.             if ((Texture_Update(theTexture)) == kQ3Failure)
  722.             {
  723.                 BP_DebugString("Document_DrawOnTexture: Q3MemoryStorage_SetBuffer failed.");
  724.                 goto bail;
  725.             }
  726.  
  727.             if (Document_Draw(*pDocument) == kQ3Failure)
  728.             {
  729.                 BP_DebugString("Document_DrawOnTexture: Document_Draw failed.");
  730.                 goto bail;
  731.             }
  732.  
  733.         }
  734.  
  735.         /*
  736.         **    Done process hits in the pick so now empty the list
  737.         */
  738.         Q3Pick_EmptyHitList(pickObject);
  739.  
  740.         from = to;
  741.     }
  742.     mainStatus = kQ3Success;
  743.  
  744. bail:
  745.  
  746.     if (pickObject != NULL) {
  747.         Q3Object_Dispose(pickObject);
  748.         pickObject = NULL;
  749.     }
  750.  
  751.     /*
  752.     **    Hide the cursor
  753.     */
  754.     Cursor3D_Hide((**pDocument).fCursor3D);
  755.     
  756.     Document_Draw(*pDocument);
  757.  
  758.     HUnlock((Handle)(**pDocument).fTexture);
  759.     HUnlock((Handle)pDocument);
  760.     
  761.     ShowCursor();
  762.  
  763.     return mainStatus;
  764.  
  765.  
  766. }
  767.  
  768. /*===========================================================================*\
  769.  *
  770.  *    Routine:    Document_GetPickingInfo()
  771.  *
  772.  *    Comments:    Gets the picking information at point of intersection.
  773.  *                The line is drawn from "from" to "to".
  774.  *                (This could be improved to handle the cases when there
  775.  *                is a failure.)
  776.  *
  777. \*===========================================================================*/
  778.  
  779. TQ3Status Document_GetPickingInfo(
  780.     DocumentHdl            theDocument,
  781.     TQ3PickObject        pickObject,
  782.     TQ3Param2D            *pTo,
  783.     TQ3GeometryObject    *pLastHitObject)
  784. {
  785.     TQ3Status            status;
  786.     Cursor3DPlacement    theCursor3DPlacement;    /*    Where we want to put the cursor    */
  787.     TQ3Vector3D            tempVector;                /*    used in calculation    */
  788.     TQ3GroupObject        theHitObject;            /*    What we hit: it's the group
  789.                                                     holding the hit object    */
  790.     TQ3HitPath            theHitPath;                /*    the group hierarchy    */
  791.     TQ3PickDetail        testDetail;                /*    Used to check for the availability
  792.                                                     of certain types of pick info    */
  793.     const float            cursorSize = 0.25;        /* size in relation to the model being
  794.                                                     drawn on */
  795.     status = kQ3Success;
  796.     theHitObject = NULL;
  797.  
  798.     /*
  799.     **    Params are as follows:
  800.     **    
  801.     **        pickObject:    the pick that we just picked (from a peck of
  802.     **                    pickled geometries)
  803.     **    
  804.     **        0:            The mouse could be over more than one
  805.     **                    geometry (because there could be some hidden
  806.     **                    behind what we can see) SOOO, we have to specify
  807.     **                    that we only want to deal with the first object
  808.     **                    (the hit list starts at 0).
  809.     **    
  810.     **        testDetail:    Returned in this parameter are flags which indicate
  811.     **                    the availability of different types of pick
  812.     **                    information (for example, the xyz location or the UV
  813.     **                    corrdinates).
  814.     **                    
  815.     */
  816.     if (Q3Pick_GetPickDetailValidMask(
  817.             pickObject,
  818.             0,
  819.             &testDetail)                            == kQ3Failure)
  820.         return kQ3Failure;
  821.  
  822.     /*
  823.     **    Get the hit object
  824.     */
  825.     if (testDetail & kQ3PickDetailMaskObject) {
  826.     
  827.         /*
  828.         **    Using the ValidMask call allows us to check to see if it's worth looking
  829.         **    at that field
  830.         */
  831.         if (Q3Pick_GetPickDetailData(
  832.                 pickObject,
  833.                 0,
  834.                 kQ3PickDetailMaskObject,
  835.                 &theHitObject)                        == kQ3Failure)
  836.                 
  837.             status = kQ3Failure;
  838.     }
  839.  
  840.     /*
  841.     **    Get the UV parameterization
  842.     **    We need this so we know where to draw into our offscreen
  843.     **    bitmap.
  844.     */
  845.     if (testDetail & kQ3PickDetailMaskUV) {
  846.     
  847.         if (Q3Pick_GetPickDetailData(
  848.                     pickObject,
  849.                     0,
  850.                     kQ3PickDetailMaskUV,
  851.                     pTo)                            == kQ3Failure)
  852.                 
  853.             status = kQ3Failure;
  854.     }
  855.  
  856.     /*
  857.     **    This is the place in xyz worldspace coordinates where we "hit"
  858.     **    the model. We want to move our cursor there so we pass in a
  859.     **    reference to the cursor location so it will be set.
  860.     */
  861.     if (testDetail & kQ3PickDetailMaskXYZ) {
  862.     
  863.         if (Q3Pick_GetPickDetailData(
  864.                     pickObject,
  865.                     0,
  866.                     kQ3PickDetailMaskXYZ,
  867.                     &theCursor3DPlacement.cursorLocation)    == kQ3Failure)
  868.                 
  869.             status = kQ3Failure;
  870.     }
  871.  
  872.     /*
  873.     **    Get the surface normal
  874.     **    We get this so we can orient the cursor.
  875.     */
  876.     if (testDetail & kQ3PickDetailMaskNormal) {
  877.     
  878.         if (Q3Pick_GetPickDetailData(
  879.                     pickObject,
  880.                     0,
  881.                     kQ3PickDetailMaskNormal,
  882.                     &tempVector)                            == kQ3Failure)
  883.                 
  884.             status = kQ3Failure;
  885.     }
  886.         
  887.     
  888.     /*
  889.     **    We negate the normal so that it is pointing *into* the model
  890.     **    because we want our cursor to point *into* the model.
  891.     */
  892.     Q3Vector3D_Negate(
  893.         (const TQ3Vector3D *)&tempVector,
  894.         &theCursor3DPlacement.toward);
  895.  
  896.     /*
  897.     **    Since we don't have an up vector, we use a utility
  898.     **    function to get one for us.
  899.     */
  900.     Utility_GetUpVector(
  901.         &theCursor3DPlacement.toward,
  902.         &theCursor3DPlacement.up);
  903.  
  904.     /*
  905.     **    Pass in our placement (everything is already normalized).
  906.     */
  907.     Cursor3D_SetPlacement(
  908.         (**theDocument).fCursor3D,
  909.         &theCursor3DPlacement) ;
  910.  
  911.     /*
  912.     **    We don't want to do this everytime
  913.     */
  914.     if (theHitObject != *pLastHitObject)
  915.     {
  916.         /*
  917.         **    This code finds the group holding the object hit and
  918.         **    scales the cursor according to it
  919.         */
  920.         
  921.         /*
  922.         **    Reset it for next time
  923.         */
  924.         *pLastHitObject = theHitObject;
  925.  
  926.         /*
  927.         **    We don't need it anymore, just the object reference
  928.         */
  929.         Q3Object_Dispose(theHitObject);
  930.     
  931.         /*
  932.         **    Get the path
  933.         */
  934.         if (testDetail & kQ3PickDetailMaskPath) {
  935.     
  936.             if (Q3Pick_GetPickDetailData(
  937.                         pickObject,
  938.                         0,
  939.                         kQ3PickDetailMaskPath,
  940.                         &theHitPath)                == kQ3Failure)
  941.                 
  942.             status = kQ3Failure;
  943.         }
  944.                     
  945.         /*
  946.         **    Get the group that holds the hit object
  947.         */
  948.         theHitObject =    Utility_GetEnclosingGroup(
  949.                             &theHitPath);
  950.  
  951.         /*
  952.         **    Change the cursor size against that group
  953.         */
  954.         Cursor3D_ChangeSizeAgainstGroup(
  955.             (**theDocument).fCursor3D,
  956.             theHitObject,
  957.             (**theDocument).fView,
  958.             cursorSize);
  959.                                         
  960.         /*
  961.         **    Empty the pick path
  962.         */
  963.         Q3HitPath_EmptyData(&theHitPath);
  964.         
  965.     }    else {
  966.     
  967.         Q3Object_Dispose(theHitObject);
  968.     }
  969.  
  970.     return status;
  971. }
  972.  
  973. /*===========================================================================*\
  974.  *
  975.  *    Routine:    Document_Idle()
  976.  *
  977.  *    Comments:    Does the Idle Action
  978.  *
  979. \*===========================================================================*/
  980.  
  981. void    Document_Idle(DocumentHdl theDocument)
  982. {
  983.     TQ3Matrix4x4        tmp;
  984.     
  985.     assert(theDocument != NULL);
  986.     assert(*theDocument != NULL);
  987.         
  988.     /*
  989.     **    For now, this just rotates the model
  990.     */
  991.  
  992.     Q3Matrix4x4_SetRotate_XYZ(&tmp, 0.025, 0.03, 0.02);
  993.     Q3Matrix4x4_Multiply(&(**theDocument).fRotation, &tmp, &(**theDocument).fRotation);
  994.                             
  995.     HLock( (Handle)theDocument  ) ;
  996.     
  997.     Document_Draw(*theDocument);
  998.  
  999.     HUnlock( (Handle)theDocument  ) ;
  1000. }
  1001.  
  1002.  
  1003. /******************************************************************************
  1004.  **                                                                             **
  1005.  **                            PRIVATE, LOCAL FUNCTIONS                         **
  1006.  **                                                                             **
  1007.  *****************************************************************************/
  1008.  
  1009. /*===========================================================================*\
  1010.  *
  1011.  *    Routine:    Document_Init()
  1012.  *
  1013.  *    Comments:    Sets All Variables and objects common to all documents
  1014.  *
  1015. \*===========================================================================*/
  1016.  
  1017. void Document_Init( DocumentHdl theDocument) 
  1018. {
  1019.     assert(theDocument    != NULL);
  1020.     assert(*theDocument    != NULL);
  1021.         
  1022.     /*
  1023.     **    NULL out all of the parameters. Check out the header file for the
  1024.     **    parameter comments
  1025.     */
  1026.     
  1027.     (**theDocument).fReferenceCount    = 0 ;
  1028.     
  1029.     (**theDocument).fWindow            = NULL ;
  1030.     
  1031.     (**theDocument).fView            = NULL;
  1032.     (**theDocument).fModel            = NULL ;
  1033.     (**theDocument).fInterpolation    = NULL ;
  1034.     (**theDocument).fBackFacing        = NULL ;
  1035.     (**theDocument).fFillStyle        = NULL ;
  1036.     Q3Matrix4x4_SetIdentity(&(**theDocument).fRotation);
  1037.  
  1038.     (**theDocument).fTexture        = NULL;
  1039.     
  1040.     (**theDocument).fCursor3D        = NULL;
  1041.  
  1042. }
  1043.  
  1044.  
  1045.  
  1046. /*===========================================================================*\
  1047.  *
  1048.  *    Routine:    Document_DoPick()
  1049.  *
  1050.  *    Comments:    Submits objects for picking and returns the number of
  1051.  *                objects hit. This should be nearly identical to
  1052.  *                Document_Draw.
  1053.  *
  1054. \*===========================================================================*/
  1055.  
  1056. static
  1057. unsigned long Document_DoPick(
  1058.     DocumentPtr        pDocument,
  1059.     TQ3PickObject    pickObject)
  1060. {
  1061.     TQ3ViewObject    aView;
  1062.     TQ3ViewStatus    viewStatus;
  1063.     unsigned long    numHits;
  1064.  
  1065.     assert(pDocument != NULL);
  1066.     
  1067.     aView   = pDocument->fView;
  1068.     numHits = 0;
  1069.  
  1070.     if (Q3View_StartPicking(aView, pickObject) == kQ3Success) {
  1071.         do {
  1072.             Document_SubmitScene( pDocument ) ;
  1073.  
  1074.             viewStatus = Q3View_EndPicking(aView);
  1075.  
  1076.         } while (viewStatus == kQ3ViewStatusRetraverse);
  1077.  
  1078.         if (viewStatus == kQ3ViewStatusDone) {
  1079.             Q3Pick_GetNumHits(pickObject, &numHits);
  1080.         }
  1081.         else {
  1082.              BP_DebugString("Document_DoPick: Q3View_EndPicking failed.");
  1083.         }
  1084.     }
  1085.     else {
  1086.         BP_DebugString("Document_DoPick: Q3View_StartPicking failed.");
  1087.     }
  1088.  
  1089.     return numHits;
  1090. }
  1091.  
  1092. /*===========================================================================*\
  1093.  *
  1094.  *    Routine:    Document_NewPick()
  1095.  *
  1096.  *    Comments:    Creates a new pick object.
  1097.  *
  1098. \*===========================================================================*/
  1099.  
  1100. static
  1101. TQ3PickObject Document_NewPick(
  1102.     TQ3WindowPointPickData    *pWPPData)
  1103. {
  1104.     if (pWPPData == NULL) {
  1105.         return NULL;
  1106.     }
  1107.     pWPPData->point.x = 
  1108.     pWPPData->point.y = 0.0;
  1109.     
  1110.     /*
  1111.     **    Create the window point pick
  1112.     */
  1113.     pWPPData->data.sort                 = kQ3PickSortNearToFar;
  1114.     pWPPData->data.numHitsToReturn    = 1;
  1115.     
  1116.     /*
  1117.     **    We want all this info
  1118.     */
  1119.     pWPPData->data.mask             =        kQ3PickDetailMaskObject
  1120.                                         |    kQ3PickDetailMaskPath
  1121.                                         |    kQ3PickDetailMaskUV    
  1122.                                         |    kQ3PickDetailMaskXYZ
  1123.                                         |    kQ3PickDetailMaskNormal
  1124.                                         ;
  1125.     pWPPData->vertexTolerance =
  1126.     pWPPData->edgeTolerance   = 3.0;
  1127.  
  1128.     return (Q3WindowPointPick_New(pWPPData));
  1129. }
  1130.  
  1131.